module dogre.log;

import std.string;
import dogre.internals.utils;

extern(C)
{
    void* getLog(const(char)* name, bool debugOutput, bool suppressFileOutput);
    void* getLogListenerWrapper(void function(void*, const(char)*, LogMessageLevel, bool, const(char)*));
    void call_addListener(void* ptr, void* ptrToListener);
}

enum //LogMessageLevel
{
    LML_TRIVIAL = 1,
    LML_NORMAL,
    LML_CRITICAL
}

alias int LogMessageLevel;

enum //LoggingLevel
{
    LL_LOW = 1,
    LL_NORMAL,
    LL_BOREME
}

alias int LoggingLevel;

class Log
{
    mixin(Wrapper);

    this(string name, bool debugOutput = true, bool suppressFileOutput = false)
    {
        p = getLog(toStringz(name), debugOutput, suppressFileOutput);
    }
    ~this(){ }
	
    void addListener(LogListener lsnr)
    {
        call_addListener(p, lsnr.ptrToWrapper);
    }
}

__gshared LogListener[void*] allListeners;

extern(C) void callListenerHandle(void* ptrToWrapper, const(char)* message, LogMessageLevel lml, bool maskDebug, const(char)* logName)
{
    if(ptrToWrapper in allListeners)
    {
        allListeners[ptrToWrapper]._handleMessage(message, lml, maskDebug, logName);
    }
}  //Called directly from the C++ code.

class LogListener
{
    public void* ptrToWrapper;  //LogListenerWrapper type
    final this()
    {
        ptrToWrapper = getLogListenerWrapper(&callListenerHandle);
        allListeners[ptrToWrapper] = this;
    }
    final ~this()
    {
        allListeners.remove(ptrToWrapper);
    }
    public void _handleMessage(const(char)* message, LogMessageLevel lml, bool maskDebug, const(char)* logName)
    {
        messageLogged(std.conv.to!string(message), lml, maskDebug, std.conv.to!string(logName));
    }
    protected abstract void messageLogged(string message, LogMessageLevel lml, bool maskDebug, string logName);
}
